package cn.com.interceptors;

import cn.com.Authorization;
import cn.com.beans.PAccount;
import cn.com.beans.PResource;
import cn.com.consts.SystemConst;
import cn.com.mapper.PAccountMapper;
import cn.com.service.PAccountService;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sound.midi.Soundbank;
import java.lang.invoke.MethodHandle;
import java.util.*;

@Component
public class SecurityIntercopter implements HandlerInterceptor , SystemConst {

    @Resource private PAccountMapper pAccountMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        String s = (String) session.getAttribute(LOGIN_STATUS);
        List<PAccount> pAccounts = pAccountMapper.selectByPhone(s);
        if (pAccounts.size() == 0) {
            response.sendRedirect(request.getContextPath()+"/account/login");
            return false;
        }
        PAccount account = pAccounts.get(0);
        System.out.println(account);
        if(account == null){
            response.sendRedirect(request.getContextPath()+"/account/login");
            return false;
        }
        if(handler instanceof HandlerMethod){
            HandlerMethod handlelMethod = (HandlerMethod) handler;
            Authorization annotation = handlelMethod.getMethodAnnotation(Authorization.class);
            if(annotation==null){
                return true;
            }
            String[] urls = (String[]) AnnotationUtils.getValue(annotation,"url");

            RequestMethod[] methods = (RequestMethod[]) AnnotationUtils.getValue(annotation, "methods");
            String  authoritys = (String) AnnotationUtils.getValue(annotation, "authority");
            List<PResource> resources = account.getResource();
            //数据结构转换
            Map<String,List<PResource>> resourceMaps = new HashMap<>();
            for(PResource resource:resources){
                if(!resourceMaps.containsKey(resource.getUrl())){
                    resourceMaps.put(resource.getUrl(),new ArrayList<>());
                }
                resourceMaps.get(resource.getUrl()).add(resource);
            }
            System.out.println(1);
            for(String url:urls){
                System.out.println(url);
                if(resourceMaps.containsKey(url)){
                    List<PResource> list = resourceMaps.get(url);
                    System.out.println(list);
                    for(PResource resource:list){
                        //鉴定URL是否匹配
                        if(url.equals(resource.getUrl())){
                            System.out.println(2);
                            //鉴定访问方式是否匹配
                            if(hasAuthority(RequestMethod.valueOf(request.getMethod()),methods)){
                                System.out.println(3);
                                //鉴定访问权限是否匹配
                                if(hasAuthority(authoritys,resource)){
                                    System.out.println(4);
                                    return true;
                                }
                            }
                        }
                    }
                }
            }


        }

        response.sendError(403,"您无权访问该功能");
        return false;
    }

    private boolean hasAuthority(String authoritys, PResource resource) {
        System.out.println(authoritys);
        System.out.println(resource);
        if(authoritys == null || authoritys.isEmpty()){
            return true;
        }
        String authority = resource.getAuthority();
        List<String> list = Arrays.asList(authority.split(","));
        List<String> list1 = Arrays.asList(authoritys.split(","));
        return Collections.disjoint(list,list1) == false;

    }

    public boolean hasAuthority(RequestMethod method,RequestMethod[] requestMethods){
        System.out.println(method);
        System.out.println(requestMethods);
        if(requestMethods.length>0){
            for(RequestMethod requestMethod:requestMethods){
                if(requestMethod == method){
                    return true;
                }
            }
            return false;
        }
        return true;
    }
}
